/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fases;

import basicas.Lata;
import java.io.IOException;
import java.util.Timer;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;
import jogo.GameDesign;
import jogo.Jogo;
import negocio.NegocioBode;
import negocio.NegocioMaterazzi;

/**
 *
 * @author tmp
 */
public abstract class Fase extends GameCanvas {

    public static final long waitTime = 50;
    protected Vector telasColisao = new Vector();
    protected Vector telasSemColisao = new Vector();
    protected Vector telasCamadasSobrepostas = new Vector();
    protected Vector latas = new Vector();
    protected Vector cacadores = new Vector();
    protected TiledLayer camadaMudarFase;
    protected TiledLayer cenario;
    protected LayerManager layerManager;
    public static final int MIN_BUFFER = 80;
    protected int viewPortX = 0;
    protected int viewPortY = 0;
    protected boolean interrupted = false;
    protected NegocioBode bode;
    protected GameDesign gameDesign = new GameDesign();
    protected Timer timer;
    protected int contador = 0;
    protected int tempo = 15;
    protected TiledLayer bodeVisto;
    protected boolean bodeMorto = false;

    public void montarImagemBodeVisto() {
        try {
            Image img = Image.createImage("/bodeVisto.png");
            bodeVisto = new TiledLayer(1, 1, img, img.getWidth(), img.getHeight());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        int[][] tiles = {
            {1}
        };
        // write mid-init user code here
        for (int row = 0; row < 1; row++) {
            for (int col = 0; col < 1; col++) {
                bodeVisto.setCell(col, row, tiles[row][col]);
            }
        }
    }

    public void reiniciarFase() {
        this.bode.reiniciar();
        this.viewPortX = 0;
        this.viewPortY = 0;
        this.getLayerManager().setViewWindow(this.getViewPortX(), this.getViewPortY(), this.getWidth(), this.getHeight());
        for (int i = 0; i < this.latas.size(); i++) {
            Lata lata = (Lata) this.latas.elementAt(i);
            lata.setTemComida(true);
            lata.getLata().nextFrame();
        }
    }

    public void comeu() {
        if (this.isComeu(bode)) {
            this.bode.addLife(this.tempo);
        }

    }

    public void morrer(Graphics g) {
        try {
            Image img = Image.createImage("/bodeMorreu.png");
            this.bodeVisto.setStaticTileSet(img, 170, 220);
            this.bodeVisto.setPosition(this.getViewPortX(), this.getViewPortY());
            this.bodeVisto.setVisible(true);
            this.layerManager.paint(g, 0, 0);
            flushGraphics(0, 0, this.getWidth(), this.getHeight());

            Thread.sleep(3000);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        this.bodeVisto.setVisible(false);
        this.bodeMorto = true;
    }

    public void ganhar(Graphics g) {
        try {
            Image img = Image.createImage("/ganhou.png");
            this.bodeVisto.setStaticTileSet(img, 170, 220);
            this.bodeVisto.setPosition(this.getViewPortX(), this.getViewPortY());
            this.bodeVisto.setVisible(true);
            this.layerManager.paint(g, 0, 0);
            flushGraphics(0, 0, this.getWidth(), this.getHeight());

            Thread.sleep(3000);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public abstract void prepararCenario() throws IOException;

    public boolean bodeVisto(Graphics g) throws InterruptedException {

        if (this.isBodeVisto(this.bode)) {
            this.bode.getSpriteBode().setVisible(false);
            if (this.bode.getVidas() >= 1) {
                this.bode.diminuirVidas();
                this.reiniciarFase();
            } else {
                this.morrer(g);
            }
            return true;
        }

        return false;
    }

    public NegocioBode getBode() {
        return this.bode;
    }

    public Fase(String nivel, NegocioBode bode) {
        super(true);
        this.layerManager = new LayerManager();
        if (bode == null) {
            this.bode = new NegocioBode();
        } else {
            this.bode = bode;
            this.bode.reiniciar();
        }
        this.timer = new Timer();
        this.montarImagemBodeVisto();

        if (nivel.equals(Jogo.FACIL)) {
            this.bode.setLife(30);
        } else if (nivel.equals(Jogo.DIFICIL)) {
            this.bode.setLife(20);
        }


    }

    public int getViewPortX() {
        return viewPortX;
    }

    public void setViewPortX(int viewPortX) {
        this.viewPortX = viewPortX;
    }

    public int getViewPortY() {
        return viewPortY;
    }

    public void setViewPortY(int viewPortY) {
        this.viewPortY = viewPortY;
    }

    public TiledLayer getCenario() {
        return cenario;
    }

    public LayerManager getLayerManager() {
        return layerManager;
    }

    public Vector getCacadores() {
        return this.cacadores;
    }

    public Vector getTelasSemColiao() {
        return this.telasSemColisao;
    }

    public Vector getTelasColisao() {
        return this.telasColisao;
    }

    public void movimentacaoBode() {
        int keyState = this.getKeyStates();
        if (((keyState & RIGHT_PRESSED)) != 0) {
            this.bode.andar(NegocioBode.DIREITA, this.cenario, telasColisao);
            this.adjustViewport(this.bode.getSpriteBode(), this.bode.getLastDirection(), this.viewPortX + NegocioBode.SPEED, this.viewPortY);
        } else if ((keyState & LEFT_PRESSED) != 0) {
            this.bode.andar(NegocioBode.ESQUERDA, this.cenario, telasColisao);
            this.adjustViewport(this.bode.getSpriteBode(), this.bode.getLastDirection(), this.viewPortX - NegocioBode.SPEED, this.viewPortY);
        } else if ((keyState & UP_PRESSED) != 0) {
            this.bode.andar(NegocioBode.CIMA, this.cenario, telasColisao);
            this.adjustViewport(this.bode.getSpriteBode(), this.bode.getLastDirection(), this.viewPortX, this.viewPortY - NegocioBode.SPEED);
        } else if ((keyState & DOWN_PRESSED) != 0) {
            this.bode.andar(NegocioBode.BAIXO, this.cenario, telasColisao);
            this.adjustViewport(this.bode.getSpriteBode(), this.bode.getLastDirection(), this.viewPortX, this.viewPortY + NegocioBode.SPEED);
        } else {
            this.bode.parar();
        }

    }

    public boolean jogar() {
        try {
            this.prepararCenario();
            this.bodeVisto.setPosition(0, 0);
            this.bodeVisto.setVisible(false);
            this.layerManager.insert(this.bodeVisto, 0);

            Graphics g = getGraphics();

            while (!this.interrupted) {

                if (this.bodeMorto) {
                    return false;
                }

                if (!this.bodeVisto(g)) {
                    this.mudarFase();
                    this.comeu();
                    this.movimentacaoBode();
                    this.movimentacaoMaterazzi();

                    this.layerManager.paint(g, 0, 0);
                    g.drawString("Vidas: " + this.bode.getVidas(), 5, 5, 20);
                    g.drawString("Tempo: " + this.bode.getLife(), 90, 5, 20);
                    flushGraphics(0, 0, this.getWidth(), this.getHeight());
                    Thread.sleep(waitTime);
                    this.contador++;
                    if (this.contador % this.tempo == 0) {
                        this.bode.diminuirLife();
                        if (this.bode.getLife() < 1) {
                            if (this.bode.getVidas() >= 1) {
                                this.bode.diminuirVidas();
                                this.reiniciarFase();
                                this.bodeVisto.setVisible(true);
                                this.layerManager.paint(g, 0, 0);
                                flushGraphics(0, 0, this.getWidth(), this.getHeight());
                                Thread.sleep(3000);
                                this.bodeVisto.setVisible(false);
                            } else {
                                this.morrer(g);
                            }
                        }
                    }
                } else {
                    this.bodeVisto.setVisible(true);
                    this.layerManager.paint(g, 0, 0);
                    flushGraphics(0, 0, this.getWidth(), this.getHeight());
                    Thread.sleep(3000);
                    this.bodeVisto.setVisible(false);
                }

            }

        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        return true;
    }

    public void stop() {
        this.interrupted = true;
    }

    private void adjustViewport(Sprite sprite, int lastDirection, int newViewPortX, int newViewPortY) {
        int sx = sprite.getX();
        int sy = sprite.getY();

        int xmin = this.viewPortX + MIN_BUFFER;
        int xmax = this.viewPortX + this.getWidth() - sprite.getWidth() - MIN_BUFFER;
        int ymin = this.viewPortY + MIN_BUFFER;
        int ymax = this.viewPortY + this.getHeight() - sprite.getHeight() - MIN_BUFFER;

        //if the sprite is not near the any screen edges don't adjust
        if (sx >= xmin && sx <= xmax && sy >= ymin && sy <= ymax) {
            return;
        }

        //if the sprite is moving left but isn't near the left edge of the screen don't adjust

        if (lastDirection == GameCanvas.LEFT && sx >= xmin) {
            return;
        }
        //if the sprite is moving right but isn't near the right edge of the screen don't adjust
        if (lastDirection == GameCanvas.RIGHT && sx <= xmax) {
            return;
        }
        //if the sprite is moving up but isn't at near top edge of the screen don't adjust
        if (lastDirection == GameCanvas.UP && sy >= ymin) {
            return;
        }
        //if the sprite is moving down but isn't at near bottom edge of the screen don't adjust
        if (lastDirection == GameCanvas.DOWN && sy <= ymax) {
            return;
        }

        //only adjust x to values that ensure the base tiled layer remains visible
        //and no white space is shown
        if (newViewPortX < cenario.getX()) {
            this.setViewPortX(cenario.getX());
        } else if (newViewPortX > cenario.getX() + cenario.getWidth() - this.getWidth()) {
            this.setViewPortX(cenario.getX() + cenario.getWidth() - this.getWidth());
        } else {
            this.setViewPortX(newViewPortX);
        }

        //only adjust y to values that ensure the base tiled layer remains visible
        //and no white space is shown
        if (newViewPortY < cenario.getY()) {
            this.setViewPortY(cenario.getY());
        } else if (newViewPortY > cenario.getY() + cenario.getHeight() - this.getHeight()) {
            this.setViewPortY(cenario.getY() + cenario.getHeight() - this.getHeight());
        } else {
            this.setViewPortY(newViewPortY);
        }

        //adjust the viewport
        this.getLayerManager().setViewWindow(this.getViewPortX(), this.getViewPortY(), this.getWidth(), this.getHeight());

    }

    private boolean colisaoPossivel(NegocioBode bode, Sprite materazzi) {
        for (int i = 0; i < this.telasCamadasSobrepostas.size(); i++) {
            TiledLayer camadaSobreposta = (TiledLayer) telasCamadasSobrepostas.elementAt(i);
            if (materazzi.collidesWith(camadaSobreposta, true) && bode.getSpriteBode().collidesWith(camadaSobreposta, true)) {
                return false;
            }
        }
        return true;
    }

    private boolean isBodeVisto(NegocioBode bode) {
        //verificar se alguma visão de algum materazzi colidiu com o sprite do bode;
        for (int i = 0; i < this.cacadores.size(); i++) {
            NegocioMaterazzi object = (NegocioMaterazzi) this.cacadores.elementAt(i);
            if (bode.getSpriteBode().collidesWith(object.getSpriteMaterazzi(), true) || bode.getSpriteBode().collidesWith(object.getSpriteVisao(), true)) {
                if (this.colisaoPossivel(bode, object.getSpriteMaterazzi()) || this.colisaoPossivel(bode, object.getSpriteVisao())) {
                    return true;
                }

            }
        }
        return false;
    }

    private boolean isComeu(NegocioBode bode) {
        for (int i = 0; i < latas.size(); i++) {
            Lata object = (Lata) latas.elementAt(i);
            if (bode.getSpriteBode().collidesWith(object.getLata(), true) && object.isTemComida()) {
                System.out.println("Comeuu");
                object.setTemComida(false);
                object.getLata().nextFrame();
                object.getLata().setTransform(Sprite.TRANS_NONE);
                object.getLata().setVisible(true);
                return true;
            }
        }
        return false;
    }

    private boolean isMudarFase(Sprite spriteBode1) {
        return spriteBode1.collidesWith(this.camadaMudarFase, false);
    }

    private void movimentacaoMaterazzi() {
        for (int i = 0; i < this.cacadores.size(); i++) {
            NegocioMaterazzi object = (NegocioMaterazzi) cacadores.elementAt(i);
            object.movimentarMaterazzi();
        }

    }

    private void mudarFase() {
        if (this.isMudarFase(this.bode.getSpriteBode())) {
            if (this instanceof FaseCidade) {
                this.ganhar(getGraphics());
            }
            this.stop();
        }
    }
}
